package com.pandora.common.db;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

import javax.sql.RowSet;

import com.pandora.common.exception.EduException;
import com.pandora.common.util.CollectionUtils;
import com.pandora.common.util.CommonUtils;
import com.pandora.common.util.StringUtils;
import com.pandora.framework.util.LogUtils;

//TODO
public class DBSession {

	private static int RSET_FETCH_SIZE = 50;
	private Connection connection = null;

	public DBSession() throws EduException {
		this.connection = DBManager.getConnection();
	}

	public RowSet executeQuery(String sql) throws EduException {
		return this.executeQuery(sql, null);
	}

	public RowSet executeQuery(String sql, ArrayList<Object> fieldList) throws EduException {
		return this.executeQuery(sql, fieldList, null);
	}

	public RowSet executeQuery(String sql, ArrayList<Object> fieldList, ArrayList<Object> fieldListSub)
			throws EduException {

		PreparedStatement pstmt = null;
		ResultSet rset = null;
		RowSet cacheSet = null;
		int fieldListSize = 0;

		try {
			pstmt = this.connection.prepareStatement(sql);
			if (CollectionUtils.isNotEmpty(fieldList)) {
				fieldListSize = fieldList.size();
				for (int i = 0; i < fieldListSize; i++) {
					pstmt.setObject(i + 1, fieldList.get(i));
				}
			}
			if (CollectionUtils.isNotEmpty(fieldListSub)) {
				for (int i = 0; i < fieldListSub.size(); i++) {
					pstmt.setObject(fieldListSize + i + 1, fieldListSub.get(i));
				}
			}
			rset = pstmt.executeQuery();
			rset.setFetchSize(RSET_FETCH_SIZE);
			// TODO 使用流缓存技术
		} catch (SQLException e) {
			String errorCode = "C000000004";
			String msg = CommonUtils.getTraceInfo() + e.getMessage();
			LogUtils.logError(errorCode, msg + "(sql=" + sql + ")");
			throw new EduException(errorCode);
		} finally {
			closeResultSet(rset);
			closePreparedStatement(pstmt);
		}

		return cacheSet;
	}

	public int executeUpdate(String sql) throws EduException {
		return executeUpdate(sql, null);
	}

	public int executeUpdate(String sql, ArrayList<Object> fieldList) throws EduException {
		return this.executeUpdate(sql, fieldList, null);
	}

	public int executeUpdate(String sql, ArrayList<Object> fieldList, ArrayList<Object> subFieldList)
			throws EduException {

		PreparedStatement pstmt = null;
		int arg = 0;
		try {
			int fieldListSize = 0;
			pstmt = this.connection.prepareStatement(sql);
			int i = 0;
			if (CollectionUtils.isNotEmpty(fieldList)) {
				fieldListSize = fieldList.size();
				for (i = 0; i < fieldList.size(); i++) {
					pstmt.setObject(i + 1, fieldList.get(i));
				}
			}
			if (CollectionUtils.isNotEmpty(subFieldList)) {
				for (i = 0; i < subFieldList.size(); i++) {
					pstmt.setObject(fieldListSize + i + 1, subFieldList.get(i));
				}
			}

			arg = pstmt.executeUpdate();
		} catch (SQLException e) {
			String errorCode = "C000000005";
			String msg = CommonUtils.getTraceInfo() + StringUtils.nullToStrTrim(e.getMessage());
			LogUtils.logError(errorCode, (msg + "(sql=" + sql + ")"));
			throw new EduException(errorCode + "(" + msg + ")");
		} finally {
			closePreparedStatement(pstmt);
		}

		return arg;
	}

	public static void closeResultSet(ResultSet rset) {
		if (rset == null) {
			return;
		}

		try {
			rset.close();
		} catch (SQLException e) {
		}

		rset = null;
	}

	public static void closePreparedStatement(PreparedStatement pstmt) {
		if (pstmt == null) {
			return;
		}

		try {
			pstmt.close();
		} catch (SQLException e) {
		}

		pstmt = null;
	}

	public static void closeConnection(Connection connection) {
		if (connection == null) {
			return;
		}

		try {
			connection.close();
		} catch (SQLException e) {
		}

		connection = null;
	}

	public void closeConnection() {
		if (this.connection != null) {
			try {
				this.connection.close();
			} catch (SQLException e) {
				String errorCode = "C000000002";
				LogUtils.log(errorCode, CommonUtils.getTraceInfo() + StringUtils.nullToStrTrim(e.getMessage()));
			}
			this.connection = null;
		}
	}

	public void commit() throws EduException {
		try {
			this.connection.commit();
		} catch (SQLException e) {
			String errorCode = "C000000006";
			LogUtils.logError(errorCode, CommonUtils.getTraceInfo() + StringUtils.nullToStrTrim(e.getMessage()));
			throw new EduException(errorCode);
		}
	}

	public void rollback() throws EduException {
		try {
			this.connection.rollback();
		} catch (SQLException e) {
			String errorCode = "C000000007";
			LogUtils.logError(errorCode, CommonUtils.getTraceInfo() + StringUtils.nullToStrTrim(e.getMessage()));
			throw new EduException(errorCode);
		}
	}

	public Connection getConnection() {
		return this.connection;
	}
}